<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>
  <script>
    // 1. 原型链继承
    {
      function A() { }
      A.prototype.age = 19
      A.prototype.say = function () {
        console.log(`来自A的原型方法`);
      }
      function B() { }
      B.prototype = new A()
      const b = new B()
      console.log(b);
    }
    // 2. 借用构造函数
    {
      function A() {
        this.a = 'aa';
        this.say = function () {
          console.log('A say');
        }
      }
      A.prototype.public = 'public';
      function B() {
        A.call(this); //this是B类的一个实例，A.call(this) 的意思是把A中的this就该成B的实例（而在B的构造函数中this就是B的实例）这样在A中通过this.xxx = xxx 的方式添加的属性都会添加到B的实例身上。
      }
      let b = new B();
      console.log(b, b.say()); // { a: 'aa', say: fun.....}
      let b2 = new B();
      console.log(b2.say === b.say); //false;
    }
    // 3. 组合继承
    {
      function A() {
        this.a = `私有的`
      }
      A.prototype.text = `公有`
      A.prototype.say = function () {
        console.log(`A的公有方法`);
      }
      function B() {
        A.call(this)
      }
      B.prototype = new A() // 原型链继承，继承父类公有和私有属性
      B.prototype.constructor = B
      const b = new B()
      console.log(b.text);
      console.log(b.a);
    }
    // 4. 原型式继承
    {
      function A() {
        this.private = `私有的`
      }
      A.prototype.public = `公有的`
      function B() { }
      B.prototype = Object.create(A.prototype)
      B.prototype.constructor = B
      const b = new B()
      console.log(b.public);
    }
    // 5. 寄生组合式继承
    {
      function A() {
        this.private = `私有的`
      }
      A.prototype.public = `共有的`
      function B() {
        A.call(this)
        this.name = `B私有的`
      }
      B.prototype = Object.create(A.prototype)
      B.prototype.constructor = B
      const b = new B()
      console.log(5, b.private);
      console.log(5, b.public);
    }
    // 6. 冒充对象继承
    {
      function A() {
        this.private = `A私有的`
      }
      A.prototype.public = `A共有的`
      function B() {
        this.name = `B私有的`
        let tep = new A()
        for (const key in tep) {
          this[key] = tep[key]
        }
      }
      const b = new B()
      console.log(b);
    }
    // es6 类的写法
    {
      class A {
        constructor(_private) {
          // 私有属性
          this._private = _private
        }
        //公有方法
        public() {
          console.log(this._private, `public`);
        }
        //静态方法
        static stat = `静态方法`
        static getStat() {
          console.log(`这是静态方法`);
        }
      }
      const a = new A(`私有的`)
      a.public()
      console.log(a._private);
      A.getStat()
      console.log(A.stat);
    }
    // 7. ES6 继承
    class A {
      constructor(_private) {
        this._private = _private
      }
      public() {
        console.log(7, `public`);
      }
    }
    class B extends A {
      constructor(a, b, c) {
        super(a)
        this.b = b
        this.c = c
      }
    }
    const b = new B(1, 2, 3)
    console.log(b);
    b.public()
    console.log(b.__proto__ === B.prototype);
    console.log(B.prototype.__proto__ === A.prototype);
  </script>
</body>

</html>